/**
 * @ProjectName： naive-admin
 * @FileName： request.ts
 * @Description: // 封装axios
 * @Author: ellwood
 * @date: 2024/1/16 - 7:41
 * @Version: V1.0.0
 */
import type { AxiosError, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig } from 'axios'
import axios from 'axios'
import i18n from '~/locales'
import { useGlobalConfig } from '~/composables/global-config.ts'
import router from '~/router'

export interface ResponseBody<T = any> {
  code: number
  data?: T
  msg: string
}

const instance = axios.create({
  baseURL: import.meta.env.VITE_APP_BASE_API ?? '/',
  timeout: 6000,
})

async function requestHandler(
  config: InternalAxiosRequestConfig,
): Promise<InternalAxiosRequestConfig> {
  const token = useAuthorization()
  /**
   * 判断是否存在token，如果存在的话，则每个http header都加上token
   */
  if (token.value)
    config.headers.set(STORAGE_AUTHORIZATION_KEY, token.value)

  return config
}

function responseHandler(
  response: AxiosResponse,
): ResponseBody<any> | AxiosResponse<any> | Promise<any> | any {
  return response.data
}

function errorHandler(error: AxiosError): Promise<any> {
  const { notification } = useGlobalConfig()
  const token = useAuthorization()

  // 判断是都存在response
  if (error.response) {
    const { data, status, statusText }
            = error.response as AxiosResponse<ResponseBody>
    // 401
    if (status === 401) {
      // 跳转到登录页面
      notification?.error({
        title: i18n.global.t('global.request.error.401'),
        content: data?.data || statusText,
        duration: 3000,
      })
      // 这里处理清空用户信息和token的逻辑，后续扩展
      token.value = null
      router
        .replace({
          path: '/login',
          query: { redirect: router.currentRoute.value.path },
        })
        .then(() => {
        })
    }
    else if (status === 403) {
      notification?.error({
        title: i18n.global.t('global.request.error.403'),
        content: data?.data || statusText,
        duration: 3000,
      })
    }
    else if (status === 500) {
      notification?.error({
        title: i18n.global.t('global.request.error.500'),
        content: data?.data || statusText,
        duration: 3000,
      })
    }
    else {
      notification?.error({
        title: i18n.global.t('global.request.error.other'),
        content: data?.data || statusText,
        duration: 3000,
      })
    }
  }
  return Promise.reject(error)
}

/**
 * 请求拦截器
 */
instance.interceptors.request.use(requestHandler)

/**
 *  响应拦截器
 */
instance.interceptors.response.use(responseHandler, errorHandler)

// ==================================封装restfulAPI增删改查的请求====================================
/**
 * 说明：
 *  1、T表示实体数据对象，默认为any,R表示是相应数据，默认也是any
 */

/**
 * 封装get请求
 * @param url url地址
 * @param params 数据
 * @param config 请求配置项
 */
export function useGet<T = any, R = any>(
  url: string,
  params?: T,
  config?: AxiosRequestConfig,
): Promise<ResponseBody<R>> {
  return instance.request({
    url,
    method: 'GET',
    params,
    ...config,
  })
}

/**
 *  封装post请求
 * @param url url地址
 * @param data 携带数据
 * @param config 请求配置项
 */
export function usePost<T = any, R = any>(
  url: string,
  data?: T,
  config?: AxiosRequestConfig,
): Promise<ResponseBody<R>> {
  return instance.request({
    url,
    data,
    method: 'POST',
    ...config,
  })
}

/**
 *  封装PUT请求
 * @param url url地址
 * @param data 携带数据
 * @param config 请求配置项
 */
export function usePut<T = any, R = any>(
  url: string,
  data?: T,
  config?: AxiosRequestConfig,
): Promise<ResponseBody<R>> {
  return instance.request({
    url,
    method: 'PUT',
    data,
    ...config,
  })
}

/**
 *  封装DELETE请求
 * @param url url地址
 * @param data 携带数据
 * @param config 请求配置项
 */
export function useDelete<T = any, R = any>(
  url: string,
  data?: T,
  config?: AxiosRequestConfig,
): Promise<ResponseBody<R>> {
  return instance.request({
    url,
    method: 'DELETE',
    data,
    ...config,
  })
}

export default instance
